#include "buzzer.h"
#include "pins_config.h"

/**
 * @brief 构造函数
 * 
 * 初始化蜂鸣器参数
 */
Buzzer::Buzzer() {
  _channel = 0;           // 使用PWM通道0
  _pin = BUZZER_PIN;      // 从pins_config.h获取引脚定义
  _resolution = 12;       // 12位分辨率(0-4095)
  _defaultFreq = 3000;    // 默认3000Hz
  _isPlaying = false;     // 初始状态为未播放
}

/**
 * @brief 初始化蜂鸣器
 * 
 * 配置LEDC的PWM通道、频率和分辨率
 * 将引脚附加到PWM通道，初始化为静音状态
 */
void Buzzer::init() {
  // 配置LEDC PWM通道
  // 参数：通道号, 频率(Hz), 分辨率(位数)
  ledcSetup(_channel, _defaultFreq, _resolution);
  
  // 将引脚附加到PWM通道
  // 参数：引脚号, PWM通道号
  ledcAttachPin(_pin, _channel);
  
  // 设置初始占空比为0，确保蜂鸣器静音
  ledcWrite(_channel, 0);
  
  _isPlaying = false;
}

/**
 * @brief 开启蜂鸣器
 * 
 * 设置50%占空比开始蜂鸣
 * 占空比 = 2^(_resolution-1) = 2^11 = 2048 (50%)
 */
void Buzzer::on() {
  // 计算50%占空比：2的(分辨率-1)次方
  uint32_t dutyCycle = pow(2, _resolution - 1);
  ledcWrite(_channel, dutyCycle);
  _isPlaying = true;
}

/**
 * @brief 停止蜂鸣
 * 
 * 将占空比设置为0，蜂鸣器停止发声
 */
void Buzzer::off() {
  ledcWrite(_channel, 0);
  _isPlaying = false;
}

/**
 * @brief 改变蜂鸣器频率
 * 
 * @param freq 目标频率(Hz)
 * 
 * 频率参考说明：
 * - 1-200Hz: 声音很小，几乎听不见
 * - 200-300Hz: 有声音，低音
 * - 400Hz: "嘟"声
 * - 500Hz: "滴"声
 * - 600-800Hz: 音调逐渐变高
 * - 2700Hz: 适合做"滴"的提示音
 * - 3000Hz: 最刺耳，声音大，适合警报
 */
void Buzzer::changeFreq(uint32_t freq) {
  // 限制频率范围，避免超出硬件限制
  if (freq > BUZZER_MAX_HZ) {
    freq = BUZZER_MAX_HZ;
  }
  
  // 改变PWM频率
  // 参数：通道号, 频率(Hz), 分辨率(位数)
  ledcChangeFrequency(_channel, freq, _resolution);
}

/**
 * @brief 播放指定频率的音调
 * 
 * @param freq 音调频率(Hz)
 * @param duration 持续时间(毫秒)，0表示持续播放
 * 
 * 如果duration为0，则持续播放直到调用off()
 * 如果duration>0，则播放指定时间后自动停止
 */
void Buzzer::playTone(uint32_t freq, uint32_t duration) {
  // 设置频率
  changeFreq(freq);
  
  // 开启蜂鸣器
  on();
  
  // 如果指定了持续时间，则延时后自动停止
  if (duration > 0) {
    delay(duration);
    off();
  }
}

/**
 * @brief 播放提示音
 * 
 * 播放一个简短的"滴"声
 * 频率：2700Hz，持续时间：100ms
 * 适合用于按键确认、操作成功等场景
 */
void Buzzer::beep() {
  playTone(2700, 100);
}

/**
 * @brief 播放警告音
 * 
 * 播放两声"滴滴"
 * 频率：2700Hz，每声100ms，间隔100ms
 * 适合用于警告、错误提示等场景
 */
void Buzzer::beepDouble() {
  playTone(2700, 100);  // 第一声
  delay(100);            // 间隔
  playTone(2700, 100);  // 第二声
}
